home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cocktail / ell.lha / ell / src / Sem.estra < prev    next >
Text File  |  1992-08-18  |  19KB  |  892 lines

  1. (*
  2.  *    ell2 - a redesign of ell
  3.  *
  4.  *    $RCSfile: Sem.estra,v $
  5.  *    
  6.  *    purpose:    semantic analysis
  7.  *
  8.  *    $Author: grosch $
  9.  *    $Date: 1992/08/07 15:32:36 $
  10.  *)
  11.  
  12. TRANSFORMATION    Semantics
  13.  
  14. GLOBAL {
  15. FROM ArgCheck    IMPORT    tLanguage, LANGUAGE;
  16. FROM Codes    IMPORT    IsCoded, IsCode, SetCode, SetDefCode, EmptyRecSetIndex,
  17.             cNoIndex, SetIndex, RecSetIndex;
  18. FROM Derivable    IMPORT    TestDerivable, IsDerivable;
  19. FROM Errors    IMPORT    eError, eWarning, eIdent, eIdentSet, eInteger,
  20.             InError, ErrorMessage, ErrorMessageI, ERROR;
  21. FROM Positions    IMPORT    NoPosition, tPosition;
  22. FROM First    IMPORT    Firsts, IsLeftRec;
  23. FROM Follow    IMPORT    Follows;
  24. FROM Idents    IMPORT    tIdent, MaxIdent, WriteIdent;
  25. FROM Reachable    IMPORT    WindThrough, IsReachable;
  26. FROM Scanner    IMPORT    NoIdent, NoValue, EndOfToken, Epsilon;
  27. FROM Sets    IMPORT    tSet, MakeSet, ReleaseSet, IsEmpty, IsSubset, IsEqual,
  28.             IsElement, Assign, Union, Difference, Include,
  29.             Exclude, AssignEmpty, Intersection, Card;
  30. FROM SYSTEM    IMPORT    ADR;
  31. FROM Table    IMPORT    InitTable, SetExpr, SetLeaf;
  32. FROM Tree    IMPORT    tTree, NoTree;
  33. FROM Types    IMPORT    BeginTypes, MakeTerm, MakeNonterm, IsDeclared,
  34.             Terminals, IsTerm, IsNonterm;
  35.  
  36. CONST
  37.   eAlreadyDeclared    = 40;
  38.   eNotDeclared        = 41;
  39.   eCodeExist        = 42;
  40.   eNoRules        = 43;
  41.   eNotReachable        = 44;
  42.   eNotDerivable        = 45;
  43.   eEnter        = 46;    (* eEnterWith = 47 *)
  44.   eByPass        = 48;    (* eByPassWith = 49 *)
  45.   eLeave        = 50;    (* eLeaveWith = 51 *)
  46.   eLeftRec        = 52;
  47.  
  48. VAR
  49.   LeftSide: tIdent;
  50.   EmptySet, EpsilonSet: tSet;
  51.  
  52. PROCEDURE IdentError    (error, class: INTEGER; pos: tPosition; ident: tIdent);
  53.   BEGIN
  54.     IF ident # NoIdent THEN
  55.       ErrorMessageI (error, class, pos, eIdent, ADR (ident));
  56.     END;
  57.   END IdentError;
  58.  
  59. PROCEDURE IntError    (error, class: INTEGER; pos: tPosition; int: INTEGER);
  60.   BEGIN
  61.     ErrorMessageI (error, class, pos, eInteger, ADR (int));
  62.   END IntError;
  63.  
  64. PROCEDURE Check        (VAR I: tSet; E: tSet; code: INTEGER; pos: tPosition);
  65.   BEGIN
  66.     IF IsSubset (I, E) THEN
  67.       ErrorMessage (code, eError, pos);
  68.     ELSE
  69.       Intersection (I, E);
  70.       IF NOT IsEmpty (I) THEN
  71.     ErrorMessageI (code+1, eWarning, pos, eIdentSet, ADR (I));
  72.       END;
  73.     END;
  74.   END Check;
  75.  
  76. CONST
  77.   MinSetSizeC        = 2;
  78.   MinCasesC        = 3;
  79.   MinSetSizeM2        = 2;
  80.   MinCasesM2        = 3;
  81.  
  82. VAR
  83.   MinSetSize: CARDINAL;
  84.   MaxDepth: INTEGER;
  85.   AnySymbol: tSet;
  86.  
  87. PROCEDURE Index    (set: tSet): INTEGER;
  88.   BEGIN
  89.     Exclude (set, Epsilon);
  90.     IF Card (set) < MinSetSize THEN
  91.       RETURN cNoIndex;
  92.     ELSE
  93.       RETURN SetIndex (set);
  94.     END;
  95.   END Index;
  96.  
  97. PROCEDURE ExpIndex    (first, follow, recovery: tSet): INTEGER;
  98.   VAR LocalFollow: tSet;
  99.   VAR result: INTEGER;
  100.   BEGIN
  101.     MakeSet (LocalFollow, MaxIdent ());
  102.     Assign (LocalFollow, follow);
  103.     Intersection (LocalFollow, recovery);
  104.       Union (LocalFollow, first);
  105.       Exclude (LocalFollow, Epsilon);
  106.       result := RecSetIndex (LocalFollow);
  107.     ReleaseSet (LocalFollow);
  108.     RETURN result;
  109.   END ExpIndex;
  110.  
  111. PROCEDURE SetMinSetSize;
  112.   BEGIN
  113.     CASE LANGUAGE OF
  114.     | C:
  115.     MinSetSize := MinSetSizeC;
  116.     MaxDepth := MinCasesC - 2;
  117.     | MODULA2:
  118.     MinSetSize := MinSetSizeM2;
  119.     MaxDepth := MinCasesM2 - 2;
  120.     END;
  121.   END SetMinSetSize;
  122. }
  123.  
  124. GRAMMAR Tree
  125.  
  126. grammar        = 
  127. | Grammar    (sections, tokens, rules)
  128.  
  129. sections    =
  130. | Sections0    ()
  131. | Sections    (section, sections)
  132.  
  133. section        =
  134. | Export    (codes)
  135. | Global    (codes)
  136. | Local        (codes)
  137. | Begin        (codes)
  138. | Close        (codes)
  139.  
  140. codes        =
  141. | Codes0    ()
  142. | Codes        (code, codes)
  143.  
  144. code        =
  145. | Code        ()
  146.  
  147. tokens        =
  148. | Tokens0    ()
  149. | Tokens    (token, tokens)
  150.  
  151. token        =
  152. | Token        (id, number)
  153.  
  154. id        =
  155. | Id        ()
  156.  
  157. number        =
  158. | Number    ()
  159.  
  160. rules        =
  161. | Rules0    ()
  162. | Rules        (rule, rules)
  163.  
  164. rule        =
  165. | Rule        (id, codes, expr)
  166.  
  167. expr        =
  168. | Option    (expr)
  169. | Times        (expr)
  170. | Plus        (expr)
  171. | List        (body: expr, sep: expr)
  172. | Action    (codes)
  173. | Leaf        (id)
  174.  
  175. expr        ->
  176. alternative    =
  177. | Alternative0    ()
  178. | Alternative    (expr, alternative)
  179.  
  180. expr        ->
  181. sequence    =
  182. | Sequence0    ()
  183. | Sequence    (expr, sequence)
  184.  
  185.  
  186.  
  187. FUNCTION    Analyse    / grammar, rules /
  188.  
  189. /*
  190.  *    semantic analysis
  191.  */
  192.  
  193.   Grammar    (sections, tokens, rules)
  194.         {
  195.         BeginTypes;
  196.         MakeTerm (Epsilon);
  197.         MakeTerm (EndOfToken);
  198.         SetCode (EndOfToken, 0);
  199.         Declare (tokens);
  200.         Declare (rules);
  201.         InitTable;
  202.         Declared (tokens);
  203.         Declared (rules);
  204.         Reduced (Grammar);
  205.         Analyse (rules);
  206.         }
  207.  
  208.   Rules0    ()
  209.         {
  210.         ErrorMessage (eNoRules, eError, NoPosition);
  211.         }
  212.  
  213.   Rules        (Rule (Id (), codes, expr), rules)
  214.         DECLARE    { VAR
  215.            RecIn, RecOut, Empty: tSet;
  216.            IsCalling: BOOLEAN;
  217.         } {
  218.         Firsts;
  219.         Follows (Id.ident);
  220.         IF InError THEN RETURN END;
  221.  
  222.         MakeSet (EmptySet , MaxIdent ());
  223.         MakeSet (EpsilonSet , MaxIdent ());
  224.         Include (EpsilonSet, Epsilon);
  225.         LL1 (Rules, EmptySet);
  226.         ReleaseSet (EmptySet);
  227.         ReleaseSet (EpsilonSet);
  228.  
  229.         MakeSet (RecIn, MaxIdent ());
  230.         MakeSet (RecOut, MaxIdent ());
  231.         Recovery (Rules, RecIn, RecOut);
  232.         ReleaseSet (RecIn);
  233.         ReleaseSet (RecOut);
  234.         SetMinSetSize;
  235.         MakeSet (AnySymbol, MaxIdent ());
  236.         Terminals (AnySymbol);
  237.         Include (AnySymbol, EndOfToken);
  238.           MakeSet (Empty, MaxIdent ());
  239.           EmptyRecSetIndex := RecSetIndex (Empty);
  240.         PrepareCode (Rules, AnySymbol, IsCalling);
  241.         ReleaseSet (AnySymbol);
  242.           ReleaseSet (Empty);
  243.         }
  244.  
  245.  
  246. FUNCTION    Declare                / tokens, token, rules /
  247.  
  248. /*
  249.  *    declare terminals
  250.  *    set codes
  251.  */
  252.  
  253.   Tokens0    () {}
  254.  
  255.   Tokens    (token, tokens)
  256.         {
  257.         Declare (token);
  258.         Declare (tokens);
  259.         }
  260.  
  261.   Token        (Id (), Number ())
  262.         {
  263.         IF IsDeclared (Id.ident) THEN
  264.           IdentError (eAlreadyDeclared, eError, Id.pos, Id.ident);
  265.           Id.ident := NoIdent;
  266.         ELSIF Id.ident # NoIdent THEN
  267.           MakeTerm (Id.ident);
  268.           IF Number.value # NoValue THEN
  269.             IF IsCode (Number.value) THEN
  270.               IntError (eCodeExist, eError, Number.pos, Number.value);
  271.             ELSE
  272.               SetCode (Id.ident, Number.value);
  273.             END;
  274.           END;
  275.         END;
  276.         }
  277.  
  278. /*
  279.  *    declare nonterminals
  280.  */
  281.  
  282.   Rules0    () {}
  283.  
  284.   Rules        (Rule (Id (), codes, expr), rules)
  285.         {
  286.         IF IsDeclared (Id.ident) THEN
  287.           IdentError (eAlreadyDeclared, eError, Id.pos, Id.ident);
  288.           Id.ident := NoIdent;
  289.         ELSE
  290.           MakeNonterm (Id.ident);
  291.         END;
  292.         Declare (rules);
  293.         }
  294.  
  295.  
  296. FUNCTION    Declared            / tokens, token, rules, expr /
  297.  
  298. /*
  299.  *    set default codes for uncoded terminals
  300.  */
  301.  
  302.   Tokens0    () {}
  303.  
  304.   Tokens    (token, tokens)
  305.         {
  306.         Declared (token);
  307.         Declared (tokens);
  308.         }
  309.  
  310.   Token        (Id (), Number ())
  311.         {
  312.         IF (Id.ident # NoIdent) & (NOT IsCoded (Id.ident)) THEN
  313.           SetDefCode (Id.ident);
  314.         END;
  315.         }
  316.  
  317. /*
  318.  *    are all leafs declared
  319.  *    set expession of nonterminals
  320.  *    collect leafs of nonterminals
  321.  */
  322.  
  323.   Rules0    ()
  324.         {}
  325.  
  326.   Rules        (Rule (Id (), codes, expr), rules)
  327.         {
  328.         LeftSide := Id.ident;
  329.         SetExpr (LeftSide, expr);
  330.         Declared (expr);
  331.         Declared (rules);
  332.         }
  333.  
  334.   Option    (expr)
  335.         {
  336.         Declared (expr);
  337.         }
  338.  
  339.   Times        (expr)
  340.         {
  341.         Declared (expr);
  342.         }
  343.  
  344.   Plus        (expr)
  345.         {
  346.         Declared (expr);
  347.         }
  348.  
  349.   List        (body: expr, sep: expr)
  350.         {
  351.         Declared (body);
  352.         Declared (sep);
  353.         }
  354.  
  355.   Action    (codes) {}
  356.  
  357.   Leaf        (Id ())
  358.         {
  359.         IF NOT IsDeclared (Id.ident) THEN
  360.           IdentError (eNotDeclared, eError, Id.pos, Id.ident);
  361.         ELSE
  362.           SetLeaf (LeftSide, Id.ident);
  363.         END;
  364.         }
  365.  
  366.   Alternative0    () {}
  367.  
  368.   Alternative    (expr, alternative)
  369.         {
  370.         Declared (expr);
  371.         Declared (alternative);
  372.         }
  373.  
  374.   Sequence0    () {}
  375.  
  376.   Sequence    (expr, sequence)
  377.         {
  378.         Declared (expr);
  379.         Declared (sequence);
  380.         }
  381.  
  382.  
  383. FUNCTION    Reduced                / grammar, rules, tokens, token /
  384.  
  385. /*
  386.  *    is the grammar reduced ? - report errors
  387.  */
  388.  
  389.   Grammar    (sections, tokens, Rules0 ())
  390.         {
  391.         }
  392.         
  393.   Grammar    (sections, tokens, Rules (Rule (Id (), codes, expr), rules))
  394.         {
  395.         WindThrough (Id.ident);
  396.         TestDerivable;
  397.         Reduced (tokens);
  398.         Reduced (Rules);
  399.         }
  400.  
  401.   Tokens0    () {}
  402.  
  403.   Tokens    (token, tokens)
  404.         {
  405.         Reduced (token);
  406.         Reduced (tokens);
  407.         }
  408.  
  409.   Token        (Id (), Number ())
  410.         {
  411.         IF NOT IsReachable (Id.ident) THEN
  412.           IdentError (eNotReachable, eWarning, Id.pos, Id.ident);
  413.         END;
  414.         }
  415.  
  416.   Rules0    ()
  417.         {
  418.         }
  419.  
  420.   Rules        (Rule (Id (), codes, expr), rules)
  421.         {
  422.         IF NOT IsReachable (Id.ident) THEN
  423.           IdentError (eNotReachable, eError, Id.pos, Id.ident);
  424.         END;
  425.         IF NOT IsDerivable (Id.ident) THEN
  426.           IdentError (eNotDerivable, eError, Id.pos, Id.ident);
  427.         END;
  428.         Reduced (rules);
  429.         }
  430.  
  431.  
  432. FUNCTION    LL1    Exclude: tSet -> / rules, expr /
  433.  
  434. /*
  435.  *    is the grammar ll1 ? - report errors and repair
  436.  */
  437.  
  438.   Rules0    ()
  439.         {}
  440.  
  441.   Rules        (Rule (Id (), codes, expr), rules)
  442.         {
  443.         IF IsLeftRec (Id.ident) THEN
  444.           IdentError (eLeftRec, eError, Id.pos, Id.ident);
  445.         END;
  446.         LL1 (expr, Exclude);
  447.         LL1 (rules, Exclude);
  448.         }
  449.  
  450.   Option    (expr)
  451.         DECLARE    {
  452.         VAR In, ByPass, Set: tSet;
  453.         } {
  454.         MakeSet (In, MaxIdent ());
  455.         MakeSet (ByPass, MaxIdent ());
  456.         MakeSet (Set, MaxIdent ());
  457.         Assign (In, expr.fifo);
  458.         Assign (ByPass, expr.follow);
  459.         Assign (Set, expr.fifo);    Union (Set, Exclude);
  460.         Check (ByPass, Set, eByPass, Option.pos);
  461.         Check (In, Exclude, eEnter, Option.pos);
  462.         ReleaseSet (In);
  463.         ReleaseSet (ByPass);
  464.         ReleaseSet (Set);
  465.         LL1 (expr, Exclude);
  466.         Difference (Option.fifo, Exclude);
  467.         }
  468.  
  469.   Times        (expr)
  470.         DECLARE    {
  471.         VAR In, Leave, Set: tSet;
  472.         } {
  473.         MakeSet (In, MaxIdent ());
  474.         MakeSet (Leave, MaxIdent ());
  475.         MakeSet (Set, MaxIdent ());
  476.         Assign (In, expr.fifo);
  477.         Assign (Leave, Times.follow);
  478.         Assign (Set, expr.fifo);    Union (Set, Exclude);
  479.         Check (Leave, Set, eLeave, Times.pos);
  480.         Check (In, Exclude, eEnter, Times.pos);
  481.         ReleaseSet (In);
  482.         ReleaseSet (Leave);
  483.         ReleaseSet (Set);
  484.         LL1 (expr, EmptySet);
  485.         Difference (Times.fifo, Exclude);
  486.         }
  487.  
  488.   Plus        (expr)
  489.         DECLARE    {
  490.         VAR In, Leave: tSet;
  491.         } {
  492.         MakeSet (In, MaxIdent ());
  493.         MakeSet (Leave, MaxIdent ());
  494.         Assign (In, Plus.fifo);
  495.         Assign (Leave, Plus.follow);
  496.         Check (Leave, In, eLeave, Plus.pos);
  497.         Check (In, Exclude, eEnter, Plus.pos);
  498.         ReleaseSet (In);
  499.         ReleaseSet (Leave);
  500.         LL1 (expr, EmptySet);
  501.         Difference (Plus.fifo, Exclude);
  502.         }
  503.  
  504.   List        (body: expr, sep: expr)
  505.         DECLARE    {
  506.         VAR In, Keep, Leave: tSet;
  507.         } {
  508.         MakeSet (In, MaxIdent ());
  509.         MakeSet (Keep, MaxIdent ());
  510.         MakeSet (Leave, MaxIdent ());
  511.         Assign (In, List.fifo);
  512.         Assign (Keep, sep.fifo);
  513.         Assign (Leave, List.follow);
  514.         Check (Leave, Keep, eLeave, List.pos);
  515.         Check (In, Exclude, eEnter, List.pos);
  516.         ReleaseSet (In);
  517.         ReleaseSet (Keep);
  518.         ReleaseSet (Leave);
  519.         LL1 (body, EmptySet);
  520.         LL1 (sep, EmptySet);
  521.         Difference (List.fifo, Exclude);
  522.         }
  523.  
  524.   Action    (codes)
  525.         DECLARE    {
  526.         VAR In: tSet;
  527.         } {
  528.         MakeSet (In, MaxIdent ());
  529.         Assign (In, Action.fifo);
  530.         Check (In, Exclude, eEnter, Action.pos);
  531.         ReleaseSet (In);
  532.         Difference (Action.fifo, Exclude);
  533.         }
  534.  
  535.   Leaf        (Id ())
  536.         DECLARE    {
  537.         VAR In: tSet;
  538.         } {
  539.         MakeSet (In, MaxIdent ());
  540.         Assign (In, Leaf.fifo);
  541.         Check (In, Exclude, eEnter, Leaf.pos);
  542.         ReleaseSet (In);
  543.         Difference (Leaf.fifo, Exclude);
  544.         }
  545.  
  546.   Alternative0    () 
  547.         {
  548.         Alternative0.depth := 0;
  549.         Difference (Alternative0.fifo, Exclude);
  550.         }
  551.  
  552.   Alternative    (expr, alternative)
  553.         DECLARE    {
  554.         VAR E2: tSet;
  555.         } {
  556.         LL1 (expr, Exclude);
  557.         MakeSet (E2, MaxIdent ());
  558.         Assign (E2, Exclude);
  559.         Union (E2, expr.fifo);
  560.         LL1 (alternative, E2);
  561.         Alternative.depth := alternative.depth + 1;
  562.         ReleaseSet (E2);
  563.         Difference (Alternative.fifo, Exclude);
  564.         }
  565.  
  566.   Sequence0    ()
  567.         DECLARE    {
  568.         VAR In: tSet;
  569.         } {
  570.         MakeSet (In, MaxIdent ());
  571.         Assign (In, Sequence0.fifo);
  572.         Check (In, Exclude, eEnter, Sequence0.pos);
  573.         Difference (Sequence0.fifo, Exclude);
  574.         }
  575.  
  576.   Sequence    (expr, sequence)
  577.         {
  578.         LL1 (expr, Exclude);
  579.         IF IsEqual (expr.first, EpsilonSet) THEN
  580.           LL1 (sequence, Exclude);
  581.         ELSE
  582.           LL1 (sequence, EmptySet);
  583.         END;
  584.         Difference (Sequence.fifo, Exclude);
  585.         }
  586.  
  587.  
  588. FUNCTION    Recovery    RecIn: tSet -> RecOut: tSet / rules, expr /
  589.  
  590. /*
  591.  *    compute the recovery sets
  592.  */
  593.  
  594.   Rules0    ()
  595.         {}
  596.  
  597.   Rules        (Rule (Id (), codes, expr), rules)
  598.         {
  599.         Recovery (expr, RecIn, RecOut);
  600.         Recovery (rules, RecIn, RecOut);
  601.         }
  602.  
  603.   Option    (expr)
  604.         {
  605.         MakeSet (Option.recovery, MaxIdent ());
  606.         Assign (Option.recovery, RecIn);
  607.         Union (Option.recovery, Option.first);
  608.         Exclude (Option.recovery, Epsilon);
  609.         Recovery (expr, RecIn, RecOut);
  610.         Assign (RecOut, Option.recovery);
  611.         }
  612.  
  613.   Times        (expr)
  614.         {
  615.         MakeSet (Times.recovery, MaxIdent ());
  616.         Assign (Times.recovery, RecIn);
  617.         Union (Times.recovery, Times.first);
  618.         Exclude (Times.recovery, Epsilon);
  619.         Recovery (expr, RecIn, RecOut);
  620.         Assign (RecOut, Times.recovery);
  621.         }
  622.  
  623.   Plus        (expr)
  624.         {
  625.         MakeSet (Plus.recovery, MaxIdent ());
  626.         Assign (Plus.recovery, RecIn);
  627.         Union (Plus.recovery, Plus.first);
  628.         Exclude (Plus.recovery, Epsilon);
  629.         Recovery (expr, RecIn, RecOut);
  630.         Assign (RecOut, Plus.recovery);
  631.         }
  632.  
  633.   List        (body: expr, sep: expr)
  634.         DECLARE    {
  635.         VAR In: tSet;
  636.         } {
  637.         MakeSet (List.recovery, MaxIdent ());
  638.         Assign (List.recovery, RecIn);
  639.         Union (List.recovery, body.first);
  640.         Union (List.recovery, sep.first);
  641.         Exclude (List.recovery, Epsilon);
  642.         MakeSet (In, MaxIdent ());
  643.         Assign (In, RecIn);
  644.         Union (In, sep.first);
  645.         Exclude (In, Epsilon);
  646.         Recovery (body, In, RecOut);
  647.         Assign (In, RecIn);
  648.         Union (In, body.first);
  649.         Exclude (In, Epsilon);
  650.         Recovery (sep, In, RecOut);
  651.         ReleaseSet (In);
  652.         Assign (RecOut, List.recovery);
  653.         }
  654.  
  655.   Action    (codes)
  656.         {
  657.         MakeSet (Action.recovery, MaxIdent ());
  658.         Assign (Action.recovery, RecIn);
  659.         Assign (RecOut, RecIn);
  660.         }
  661.  
  662.   Leaf        (Id ())
  663.         {
  664.         MakeSet (Leaf.recovery, MaxIdent ());
  665.         Assign (RecOut, RecIn);
  666.         Union (RecOut, Leaf.first);
  667.         Exclude (RecOut, Epsilon);
  668.         IF IsTerm (Id.ident) THEN
  669.           Assign (Leaf.recovery, RecOut);
  670.         ELSE
  671.           Assign (Leaf.recovery, RecIn);
  672.         END;
  673.         }
  674.  
  675.   Alternative0    ()
  676.         {
  677.         ERROR ('Sem.estra: Alternative0 unexpected');
  678.         }
  679.  
  680.   Alternative    (:expr, :alternative)
  681.         DECLARE    {
  682.         VAR RecUnion: tSet;
  683.         } {
  684.         MakeSet (RecUnion, MaxIdent ());
  685.         Assign (RecUnion, RecIn);
  686.         RecoveryAlt (Alternative, RecIn, RecUnion, RecOut);
  687.         ReleaseSet (RecUnion);
  688.         }
  689.  
  690.   Sequence0    ()
  691.         {
  692.         MakeSet (Sequence0.recovery, MaxIdent ());
  693.         Assign (Sequence0.recovery, RecIn);
  694.         Assign (RecOut, RecIn);
  695.         }
  696.  
  697.   Sequence    (expr, sequence)
  698.         {
  699.         MakeSet (Sequence.recovery, MaxIdent ());
  700.         Recovery (sequence, RecIn, RecOut);
  701.         Recovery (expr, RecOut, Sequence.recovery);
  702.         Assign (RecOut, Sequence.recovery);
  703.         }
  704.  
  705.  
  706. FUNCTION    RecoveryAlt    RecIn: tSet; RecUnion: tSet -> RecOut: tSet
  707.                         / alternative /
  708.  
  709. /*
  710.  *    compute the recovery sets (alternative)
  711.  */
  712.  
  713.   Alternative0    ()
  714.         {
  715.         MakeSet (Alternative0.recovery, MaxIdent ());
  716.         Exclude (RecUnion, Epsilon);
  717.         Assign (Alternative0.recovery, RecUnion);
  718.         Assign (RecOut, RecUnion);
  719.         }
  720.  
  721.   Alternative    (expr, alternative)
  722.         {
  723.         MakeSet (Alternative.recovery, MaxIdent ());
  724.         Recovery (expr, RecIn, RecOut);
  725.         Union (RecUnion, expr.first);
  726.         RecoveryAlt (alternative, RecIn, RecUnion, RecOut);
  727.         Assign (Alternative.recovery, RecOut);
  728.         }
  729.  
  730.  
  731. FUNCTION    PrepareCode    PossibleTerms: tSet -> IsCalling: BOOLEAN / rules, expr /
  732.  
  733. /*
  734.  *    prepare the code generation
  735.  */
  736.  
  737.   Rules0    ()
  738.         {}
  739.  
  740.   Rules        (Rule (Id (), codes, expr), rules)
  741.         {
  742.         PrepareCode (expr, PossibleTerms, Rule.iscalling);
  743.         PrepareCode (rules, PossibleTerms, IsCalling);
  744.         }
  745.  
  746.   Option    (expr)
  747.         {
  748.         Option.index := Index (Option.first);
  749.         Option.followindex := Index (Option.follow);
  750.         Option.expindex := ExpIndex (Option.first, Option.follow, Option.recovery);
  751.         Option.recindex := RecSetIndex (Option.recovery);
  752.         PrepareCode (expr, expr.fifo, IsCalling);
  753.         }
  754.  
  755.   Times        (expr)
  756.         {
  757.         Times.index := Index (Times.first);
  758.         Times.followindex := Index (Times.follow);
  759.         Times.expindex := ExpIndex (Times.first, Times.follow, Times.recovery);
  760.         Times.recindex := RecSetIndex (Times.recovery);
  761.         PrepareCode (expr, expr.fifo, IsCalling);
  762.         }
  763.  
  764.   Plus        (expr)
  765.         DECLARE    {
  766.         VAR set: tSet;
  767.         } {
  768.         Plus.index := Index (Plus.first);
  769.         Plus.followindex := Index (Plus.follow);
  770.         Plus.expindex := ExpIndex (Plus.first, Plus.follow, Plus.recovery);
  771.         Plus.recindex := RecSetIndex (Plus.recovery);
  772.         MakeSet (set, MaxIdent ());
  773.         Assign (set, PossibleTerms);
  774.         Union (set, expr.fifo);
  775.         PrepareCode (expr, set, IsCalling);
  776.         ReleaseSet (set);
  777.         }
  778.  
  779.   List        (body: expr, sep: expr)
  780.         DECLARE    {
  781.         VAR iscalling: BOOLEAN;
  782.         } {
  783.         List.index := Index (List.first);
  784.         List.followindex := Index (List.follow);
  785.         List.expindex := ExpIndex (sep.first, List.follow, List.recovery);
  786.         List.recindex := RecSetIndex (List.recovery);
  787.         PrepareCode (body, AnySymbol, iscalling);
  788.         PrepareCode (sep, AnySymbol, IsCalling);
  789.         IsCalling := IsCalling OR iscalling;
  790.         }
  791.  
  792.   Action    (codes) { IsCalling := FALSE; }
  793.  
  794.   Leaf        (Id ())
  795.         {
  796.         Leaf.sure := IsSubset (PossibleTerms, Leaf.fifo);
  797.         IF Leaf.sure OR IsNonterm (Id.ident) THEN
  798.           Leaf.index := cNoIndex;
  799.         ELSE
  800.           Leaf.index := Index (Leaf.first);
  801.         END;
  802.         Leaf.recindex := RecSetIndex (Leaf.recovery);
  803.         (* Leaf.followindex := Index (Leaf.follow); *)
  804.         IsCalling := IsNonterm (Id.ident);
  805.         }
  806.  
  807.   Alternative0    ()
  808.         {
  809.         ERROR ('Sem.estra: Alternative0 unexpected');
  810.         }
  811.  
  812.   Alternative    (:expr, :alternative)
  813.         DECLARE    {
  814.         VAR case: BOOLEAN; maxdepth: INTEGER;
  815.         } {
  816.         maxdepth := MaxDepth;
  817.         IF IsSubset (PossibleTerms, Alternative.fifo) (* OR IsElement (Epsilon, Alternative.first) *) THEN
  818.           INC (maxdepth);
  819.         END;
  820.         case := Alternative.depth > maxdepth;
  821.         PrepareCodeAlt (Alternative, case, PossibleTerms, Alternative.first, NoTree, IsCalling);
  822.         }
  823.  
  824.   Sequence0    () { IsCalling := FALSE; }
  825.  
  826.   Sequence    (expr, sequence)
  827.         DECLARE    {
  828.         VAR iscalling: BOOLEAN;
  829.         } {
  830.         PrepareCode (expr, PossibleTerms, iscalling);
  831.         IF IsElement (Epsilon, expr.first) & (Card (expr.first) = 1) THEN
  832.           PrepareCode (sequence, PossibleTerms, IsCalling);
  833.         ELSE
  834.           PrepareCode (sequence, AnySymbol, IsCalling);
  835.         END;
  836.         IsCalling := IsCalling OR iscalling;
  837.         }
  838.  
  839.  
  840. FUNCTION    PrepareCodeAlt    Case: BOOLEAN;
  841.                 PossibleTerms: tSet;
  842.                 First: tSet;
  843.                 Default: tTree -> IsCalling: BOOLEAN / alternative /
  844.  
  845. /*
  846.  *    prepare the code generation (alternative)
  847.  */
  848.  
  849.   Alternative0    ()
  850.         DECLARE {
  851.         VAR LocalFollow: tSet;
  852.         } {
  853.             MakeSet (LocalFollow, MaxIdent ());
  854.             Assign (LocalFollow, Alternative0.follow);
  855.             Intersection (LocalFollow, Alternative0.recovery);
  856.             IF NOT IsEmpty (LocalFollow) OR NOT IsElement (Epsilon, First) THEN
  857.                 Union (LocalFollow, First);
  858.                 Exclude (LocalFollow, Epsilon);
  859.           Alternative0.expindex := RecSetIndex (LocalFollow);
  860.             ELSE
  861.           Alternative0.expindex := cNoIndex;
  862.             END;
  863.             ReleaseSet (LocalFollow);
  864.  
  865.         Alternative0.case := Case;
  866.         Alternative0.default := Default;
  867.         Alternative0.recindex := RecSetIndex (Alternative0.recovery);
  868.         (* Alternative0.followindex := Index (Alternative0.follow); *)
  869.         IsCalling := FALSE;
  870.         }
  871.  
  872.   Alternative    (e1:expr, alternative)
  873.         DECLARE    {
  874.         VAR possible: tSet; iscalling: BOOLEAN;
  875.         } {
  876.         Alternative.case := Case;
  877.         PrepareCode (e1, e1.fifo, iscalling);
  878.         MakeSet (possible, MaxIdent ());
  879.         Assign (possible, PossibleTerms);
  880.         IF (Default = NoTree) OR (Default^.expr.length > e1.length) THEN
  881.           Default := e1;
  882.         END;
  883.         Difference (possible, e1.fifo);
  884.         IF NOT Case THEN
  885.            Alternative.index := Index (e1.fifo);
  886.         END;
  887.         (* Alternative.followindex := Index (Alternative.follow); *)
  888.         PrepareCodeAlt (alternative, Case, possible, First, Default, IsCalling);
  889.         IsCalling := IsCalling OR iscalling;
  890.         ReleaseSet (possible);
  891.         }
  892.